'''元组拆包即从元组中提取不同端的信息，我们可以将这一操作理解为平行赋值。
也就是说拆包会把一个可迭代对象中的元素一并赋值到对应变量中去。
这样做可以让我们把注意力集中在我们所需要关注的元素上面。
'''
tuple1 = ('阿Z',182,'72kg')

name,tall,weight = tuple1

print(name,tall,weight) # 阿Z 182 72kg

'''
不确定参数 “*” 和占位符 “_”。
在拆包的时候我们可以使用“*”来处理剩下的参数，Python中常用这种方法来代表不确定参数。
'''
# *的用法
a, b, *others = ('阿Z',182,'72kg')
print(a, b, others) # 0 1 [2, 3, 4]

# _的用法
name, _,weight  = ('阿Z',182,'72kg')
print(name, weight) # 阿Z 72kg

# *_的用法

name, *_, favor  = ('阿Z', 182, '72kg', 'cold', 'joke')
print(name, favor) # 阿Z joke


'''
当函数的参数不确定时候可以用 *args 和 **kwargs。
*args 是用于接收多余的未命名参数，**kwargs 用于接收实参中的命名参数，
其中 args 是一个元组类型，而 kwargs 是一个字典类型的数据。
形参中的 *args 把传进来的数据放在了 args 这个元组中。
把 **kwargs 传进来的数据放在了 kwargs 这个字典中。
'''

# *args 其实就是把**元组中的数据进行拆包**，也就是把元组中的数据拆成单个数据。
def print_everything(*arg):
    for num, thing in enumerate(arg):
        print(num, thing)

print_everything('阿Z', '阿Y') 

# 调用结果为:
# 0 阿Z
# 1 阿Y

# **kwargs 就是把 **字典中的数据进行拆包**，传进的命名数据可以从 kwargs 按键进行索引获

def print_info(**kwargs):
    for name, tall in kwargs.items():
        print('{0} = {1}'.format(name, tall))

print_info(name='阿Z', tall=182) 

# 调用结果为:
# name = 阿Z
# tall = 182

# 如果将这俩个参数同时使用

def print_more(msg, *arg, **kwargs):
    print(msg)

    if arg:
        print(arg)

    if kwargs:
        print(kwargs)

# 直接调用 func() 函数会报错：func（）至少需要1个参数
# print_more()

# TypeError: print_more() missing 1 required positional argument: 'msg'

# 给定一个参数
print_more('这是一条信息')

# 这是一条信息
# 调用 func() 函数的时候给定了一个参数，所以只会打印一个参数。

# 给定*arg参数
print_more('这是一条信息', 1, 2, '3')

# 这是一条信息
# (1, 2, '3')
# *args 接受了剩余的参数并放到了元组中


# 给定所有参数
print_more('这是一条信息', 1, 2, '3', length=9, string=7)

# 这是一条信息
# (1, 2, '3')
# {'length': 9, 'string': 7}
# **args接受了无 Key 值的参数并放到元组中，**kwargs 接收了有 key 值的参数并放到了字典中。